package com.ttbj.log;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.ttbj.api.dto.SalesmanDto;
import com.ttbj.api.dto.log.SystemLogDto;
import com.ttbj.api.systemlog.SystemLogService;
import com.ttbj.constant.Const;
import com.ttbj.constant.annotation.SystemControllerLog;
import com.ttbj.core.util.CommUtil;
import com.ttbj.dto.ViewData;


@Aspect
public class LoggerRecord {
	
	@Resource
	private SystemLogService systemLogService;
	@Autowired
	private HttpServletRequest httpServletRequest;

	private static Logger LOGGER = LoggerFactory.getLogger(LoggerRecord.class); 
	
	//Controller层切点
	@Pointcut("@annotation(com.ttbj.constant.annotation.SystemControllerLog)")
	public void controllerAspect(){
		
	}
	
	//通过连接点获取当前被增强的类，方法等很多信息
	public void beforeLogger(JoinPoint joinPoint){
		
	}
	
	//后置通知，用于拦截Controller层记录用户的操作
	@AfterReturning(pointcut="controllerAspect()", returning="result")
	public void afterContReturningLogger(JoinPoint joinPoint, Object result){
		//得到当前用户
		SalesmanDto authUserInfo = (SalesmanDto) httpServletRequest.getSession().getAttribute(Const.TTBJ_USER_SESSION_KEY);
		//使用JSONObject获取ViewData对象
		ViewData viewData = JSON.parseObject((String)result, ViewData.class);
		//获取ViewData对象中status属性
		int status = viewData.getStatus();
		//如果user不是空的，而且status为0【为0说明成功执行】
		if (authUserInfo != null && status == 0) {
			try {
				SystemLogDto systemLogDto = new SystemLogDto();
				systemLogDto.setDescription(getControllerMethodDescription(joinPoint));	//日志描述
				systemLogDto.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
				systemLogDto.setType(0);		//日志类型，正常操作
				systemLogDto.setRequestIp(CommUtil.getIpAddr(httpServletRequest));	//ip解析成 ：中国 山东 济南 联通
				systemLogDto.setParams(optionContent(joinPoint.getArgs(), joinPoint.getSignature().getName()));	//获取参数
				systemLogDto.setCreateBy(authUserInfo.getSalesmanName());	//哪个管理员操作
				systemLogDto.setCreateDate(new Date());	
				//日志记录保存操作
				this.systemLogService.addToSystemLogInfo(systemLogDto);
			} catch (Exception e) {
				e.printStackTrace();
				//记录本地异常日志
				LOGGER.error("后置增强异常，异常信息{}", e);
			}
		}
	}
	
	/**
	 * 获取注解中对方法的描述  用于controller层
	 * @param joinPoint
	 * @return 描述信息
	 * @throws Exception
	 */
	public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception{
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Class targetClass = Class.forName(targetName);
		Method[] methods = targetClass.getMethods();
		String description = "";
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					description = method.getAnnotation(SystemControllerLog.class).description();
					break;
				}
			}
		}
		return description;
	}
	
	
	/**
	 * 使用Java反射来获取被拦截方法(insert、update)的参数值， 将参数值拼接为操作内容
	 * @param args
	 * @param mName
	 * @return
	 */
	public String optionContent(Object[] args, String mName) {
		if (args == null) {
			return null;
		}
		StringBuffer rs = new StringBuffer();
		rs.append(mName);
		String className = null;
		int index = 1;
		System.out.println("参数数组：" + Arrays.toString(args));
		// 遍历参数对象
		for (Object info : args) {
			// 获取对象类型
			className = info.getClass().getName();
			className = className.substring(className.lastIndexOf(".") + 1);
			rs.append("[参数" + index + "，类型:" + className + "，值:");
			// 获取对象的所有方法
			Method[] methods = info.getClass().getDeclaredMethods();
			// 遍历方法，判断get方法
			for (Method method : methods) {
				String methodName = method.getName();
				// 判断是不是get方法
				if (methodName.indexOf("get") == -1) {// 不是get方法
					continue;// 不处理
				}
				Object rsValue = null;
				try {
					// 调用get方法，获取返回值
					rsValue = method.invoke(info);
				} catch (Exception e) {
					continue;
				}
				// 将值加入内容中
				rs.append("(" + methodName + ":" + rsValue + ")");
			}
			rs.append("]");
			index++;
		}
		return rs.toString();
	}
}
